package eitwitter.evaluation;


import eitwitter.learning.Learning;
import eitwitter.storage.Category;
import eitwitter.storage.Tweet;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.EnumMap;

/**
 * Evaluation simple se servant uniquement des resultats de la classe Learning
 * @author AH & PJ
 */
public class SimpleEvaluation implements Evaluation{

	/** Reference vers la classe d'apprentissage */
	private Learning learning;

	/**
	 * Constructeur de l'evaluation simple
	 * @param learning Reference vers la classe d'apprentissage completee
	 */
	public SimpleEvaluation(Learning learning) {
		this.learning = learning;
	}

	/**
	 * Determine la categorie du tweet en comparant les inferences suivant les 
	 * categories sur lesquelles s'est fait l'apprentissage
	 * @param tweet Tweet dont on veut determiner la categorie
	 */
	@Override
	public void computeTweetCategory(Tweet tweet) {

		// Contiendra le resultat de l'analyse
		Category result = null;

		// Calcul des inferences pour chaque categorie
		EnumMap<Category, Double> inferences = new EnumMap<Category, Double>(Category.class);

		// Inference maximale trouvee
		double max = Double.NEGATIVE_INFINITY;
		
		// Parcours de toutes les categories existantes
		for(Category c : Category.values()){

			// Calcul de l'inférence pour la catégorie
			double inference = learning.computeInference(tweet, c);
			
			// Stockage pour debogage surtout
			inferences.put(c, inference);

			// Recherche de l'inference maximale
			if(inference > max){
				max = inference;
				result = c;
			}
		}

		// Mise a jour de la categorie du tweet
		tweet.setCategory(result);
	}

	@Override
	public EnumMap<Category, EnumMap<Category, Integer>> computeConfusionMatrix(File file) {
		// Matrice de confusion
		EnumMap<Category, EnumMap<Category, Integer>> matrix = new EnumMap<Category, EnumMap<Category,Integer>>(Category.class);
		// Initialisation de toutes les categories réelles possibles
		for(Category category : Category.values()){
			EnumMap<Category, Integer> tmp = new EnumMap<Category, Integer>(Category.class);
			// Initialisation de toutes les categories évaluées possibles
			for(Category category2 : Category.values()){
				tmp.put(category2, 0);
			}
			// Ajout à la matrice
			matrix.put(category, tmp);
		}

		try {
			// Ouverture du fichier
			InputStream ips = new FileInputStream(file);
			InputStreamReader ipsr = new InputStreamReader(ips);
			BufferedReader br = new BufferedReader(ipsr);

			// Traitement de la ligne en cours
			String line;
			while ((line=br.readLine())!=null){
				// Creation de l'objet Tweet pour la ligne lue
				Tweet t = Tweet.createFromString(line);
				// Récupération de la vraie catégorie
				Category trueCategory = t.getCategory();

				// Si une compagny est définie dans le learning
				if(this.learning.getCompany()!=null){
					// Si cette company est la même que celle du tweet
					if(this.learning.getCompany()==t.getCompany()){
						// Evaluation de la catégorie
						this.computeTweetCategory(t);
						// Récupération de la catégorie évaluée
						Category evalCategory = t.getCategory();
		
						// Modification de la matrice
						EnumMap<Category, Integer> tmp = matrix.get(trueCategory);
						tmp.put(evalCategory, tmp.get(evalCategory)+1);
						matrix.put(trueCategory, tmp);
					}
				}else{
					// Evaluation de la catégorie
					this.computeTweetCategory(t);
					// Récupération de la catégorie évaluée
					Category evalCategory = t.getCategory();
	
					// Modification de la matrice
					EnumMap<Category, Integer> tmp = matrix.get(trueCategory);
					tmp.put(evalCategory, tmp.get(evalCategory)+1);
					matrix.put(trueCategory, tmp);
				}

			}

			// Fermeture des pointeurs
			br.close();
			ips.close();

		} catch (IOException ex) {
			ex.printStackTrace();
		}
		
		return matrix;
	}

	@Override
	public void printTweetCategories(File file) {
		try {
			// Ouverture du fichier
			InputStream ips = new FileInputStream(file);
			InputStreamReader ipsr = new InputStreamReader(ips);
			BufferedReader br = new BufferedReader(ipsr);

			// Traitement de la ligne en cours
			String line;
			while ((line=br.readLine())!=null){
				// Creation de l'objet Tweet pour la ligne lue
				Tweet t = Tweet.createFromString(line);


				// Si une compagny est définie dans le learning
				if(this.learning.getCompany()!=null){
					// Si cette company est la même que celle du tweet
					if(this.learning.getCompany()==t.getCompany()){
						// Evaluation de la catégorie
						this.computeTweetCategory(t);
						// Affichage du tweet
						System.out.println(t.getCategory().toString().toLowerCase());
						
					}
				}else{
					// Evaluation de la catégorie
					this.computeTweetCategory(t);
					// Affichage du tweet
					System.out.println(t.getCategory().toString().toLowerCase());
				}

			}

			// Fermeture des pointeurs
			br.close();
			ips.close();

		} catch (IOException ex) {
			ex.printStackTrace();
		}
	}

}
